package com.gitee.dengmin.logback;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.Map;

/**
 * @Author dengmin
 * @Created 2020/6/9 下午4:33
 */
public class KafkaAppender {
    Logger logger = LoggerFactory.getLogger(KafkaAppender.class);

    private static final long serialVersionUID = 1L;

    private String appName;
    private String hosts;
    private String topic;

    private ObjectMapper mapper = new ObjectMapper();

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public void setHosts(String hosts) {
        this.hosts = hosts;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    protected void append(ILoggingEvent iLoggingEvent) {
        LogMessage logMessage = new LogMessage();
        logMessage.setAppName(appName);
        logMessage.setClassName(iLoggingEvent.getLoggerName());
        logMessage.setLevel(iLoggingEvent.getLevel().toString());
        logMessage.setMethod(iLoggingEvent.getThreadName());
        logMessage.setMessage(processMessage(iLoggingEvent));
        //日志生产的时间
        logMessage.setDateTime(new Date(iLoggingEvent.getTimeStamp()));
        logMessage.setTimestamp(iLoggingEvent.getTimeStamp());

        //MDC请求跟踪
        Map<String,String> mdc = iLoggingEvent.getMDCPropertyMap();
        String traceId = mdc.get("REQUEST-ID");
        if(null != traceId && traceId.length()>0){
            logMessage.setTraceId(traceId);
        }

        //获取行号
        StackTraceElement[] stackTraceElement = iLoggingEvent.getCallerData();
        if(null !=stackTraceElement && stackTraceElement.length > 0 && stackTraceElement[0] != null){
            StackTraceElement element = stackTraceElement[0];
            logMessage.setLine(element.getLineNumber());
        }

        try {
            //转换成json格式
            String msg = mapper.writeValueAsString(logMessage);
            KafkaProduceClient.getInstance(hosts).push(topic, msg);
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 处理异常信息
     * @param event
     * @return
     */
    private String processMessage(ILoggingEvent event){
        if(event.getLevel().equals(Level.ERROR)){
            if(event.getThrowableProxy() != null){
                ThrowableProxy proxy = (ThrowableProxy) event.getThrowableProxy();
                return getStackTrace(proxy.getThrowable());
            }else {
                return event.getFormattedMessage();
            }
        }
        return event.getFormattedMessage();
    }

    private String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);
        throwable.printStackTrace(pw);
        return sw.getBuffer().toString();
    }
}
